package com.cskaoyan.javase._1extends._8hidden;

import javax.swing.*;

/**
 * 属性的隐藏
 * 父子类中出现同名的成员变量是可以的,那么如果创建子类对象
 * 访问该同名成员变量,结果是什么呢?
 * 我们发现访问的结果是子类中成员变量的取值.
 * 为什么?
 *      1.被覆盖掉了
 *      2.被隐藏掉了
 * 很明显,属性是不可能被覆盖的,父子类成员变量存储在子类对象中的不同区域
 * 而是由于某种访问机制,属性被隐藏了,这种现象称之为"属性的隐藏"
 *
 * 这种访问机制就是,"对象名.成员变量"的访问机制.
 * 现在我们要研究一下这种访问机制.
 * 研究"对象名.成员变量"的访问机制,要从两个角度来研究:
 *      1.访问的范围(就是能够访问哪些成员变量,父类?子类?还是父子类都有?)
 *      2.访问的结果
 *
 * 当然,存在继承后,有父子类,创建对象的方式,就有了三种:
 *      1.子类引用指向子类对象
 *      2.父类引用指向父类对象
 *      3.父类引用指向子类对象(子类"is-a"父类,向上转型,自动类型转换)
 *
 *
 * 接下来用代码的输出研究,"对象名.成员变量"的访问范围:
 *      1.子类引用指向子类对象
 *          访问范围是"父类 + 子类"
 *
 *      2.父类引用指向父类对象
 *          访问范围是"父类"
 *
 *      3.父类引用指向子类对象
 *          如果访问范围是"父类 + 子类"
 *              说明访问范围看: 对象
 *          如果访问范围是"父类"
 *              说明访问范围看: 引用
 *          在不做强转的情况下, 访问范围只有"父类"
 *
 * 以上三个实验,说明"对象名.成员变量"访问范围要看引用的数据类型:
 *       1.如果引用是父类类型,那么访问范围是"父"
 *       2.如果引用是子类类型,那么访问范围是"父+子"
 *
 * 在Java当中，对象名点访问成员变量的范围是编译器决定的，是一个编译上的概念。
 * 编译器在检索一个引用是否能够访问到某个成员变量时，存在以下检索机制：
 *      1.首先编译器会从引用的数据类型的那个类中，去查找该成员变量。
 *          如果找到了，就直接认为它可以访问。（有权限才行）
 *      2.如果从引用的数据类型中没有找到，那么就去引用类型的父类中找。
 *          直到找到Object类，如果全程都没有该成员变量，那就会编译报错。(说明这个成员变量是瞎写的,根本就没有)
 *
 * 上述规则，实际上可以总结为：
 *      在Java中，访问范围是可以往上查找父类的，但不能往下找子类。
 *      子类知道自己的"爸爸"是谁，但"爸爸"并不知道它有这个"儿子"，甚至都不知道自己有几个"儿子"，或者有没有"儿子"。
 *
 * 总结:
 *      访问范围是一个编译概念,要看引用的数据类型,并且可以往上找引用类型的父类,但是不能往下找子类.
 *
 *
 * 接下来用代码的输出研究,"对象名.成员变量"的访问结果:
 *      1.子类引用指向子类对象
 *          体现出子类中的成员变量取值
 *          如果访问的是父类独有的成员变量
 *              那就体现出父类中的成员变量取值
 *
 *      2.父类引用指向父类对象
 *          体现出父类中成员变量的取值
 *          父类不能访问子类
 *
 *      3.父类引用指向子类对象
 *          如果访问同名成员变量
 *          如果结果是父类中的取值
 *              说明,访问结果看: 引用
 *          如果结果是子类中的取值:
 *              说明,访问结果看: 对象
 *          通过实验结果,发现
 *          "对象名.成员变量"的访问结果要看引用
 *          引用是什么类型,该成员变量的结果就是该类中的取值.
 *      对象名点成员变量，访问的结果也是由 引用的数据类型 来决定的。
 *
 * 以上总结:
 * 如果引用是父类类型，那么它的访问结果一定也是父类中的结果。
 * 如果引用是子类类型，那么它的访问结果一定也是子类中的结果。
 *
 * 综合对象名点访问成员变量的范围和结果，发现：都是根据引用的数据类型来决定的，无需考虑是何种对象。
 *
 * @since 09:32
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        /*Son s = new Son();
        System.out.println(s.num);
        System.out.println(s.getNum());*/

        Son s = new Son();
        System.out.println(s.num);
        System.out.println(s.fatherNum);
        System.out.println(s.sonNum);

        Father f = new Father();
        System.out.println(f.fatherNum);
        System.out.println(f.num);
        // f.sonNum.sout

        Father fs = new Son();
        System.out.println(fs.fatherNum);
        System.out.println(fs.num);
        /*
            fs是父类引用不能直接访问子类独有成员变量
            而是需要做一次强转,强转成子类引用
            才可以访问子类独有的成员变量
         */
        // fs.sonNum.sout
        // System.out.println(((Son) fs).sonNum);

    }
}

class Father {
    int num = 10;
    int fatherNum = 20;

    /*public int getNum() {
        return num;
    }*/
}

class Son extends Father {
    int num = 100;
    int sonNum = 200;
}